package com.xwj;

import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 滑动时间窗算法
 * 假设某个服务最多只能每秒钟处理100个请求，我们可以设置一个1秒钟的滑动时间窗口
 * 窗口中有10个格子，每个格子100毫秒，每100毫秒移动一次，每次移动都需要记录当前服务请求的次数
 */
public class SlidingTimeWindow {
    /**
     * 服务访问次数
     */
    private Long counter = 0L;
    /**
     * 时间窗
     */
    private LinkedList<Long> slots = new LinkedList<Long>();
    private volatile boolean limitFlag = false;

    public static void main(String[] args) throws InterruptedException {
        SlidingTimeWindow slidingTimeWindow = new SlidingTimeWindow();
        new Thread(()->{
            slidingTimeWindow.doCheck();
        }).start();

        while (true) {
            slidingTimeWindow.counter++;
            if(!slidingTimeWindow.limitFlag) {
                System.out.println(slidingTimeWindow.counter+"pass");
            } else {
                System.out.println("限流。。。。。。" + slidingTimeWindow.counter);
            }
            TimeUnit.MILLISECONDS.sleep(new Random().nextInt(15));
        }
    }

    private void doCheck() {
        while (true) {
            slots.addLast(counter);
            if(slots.size() > 10) {
                slots.removeFirst();
            }
            //比较最后一个和第一个，两者相差100以上就限流
            if(slots.peekLast() - slots.peekFirst() > 100) {
                // 设置限流标识为true
                limitFlag = true;
            } else {
                // 设置限流标识为false
                limitFlag = false;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
